#ifndef __MGGS_MESH__
#define __MGGS_MESH__

#include "Point.h"
#include <valarray>
#include <fstream>
#include <string>



class EasyMesh{
private:
  std::valarray<Point<double,2>> nodes;
  std::valarray<Vector<int,3>> grids;
public:
  EasyMesh();
  EasyMesh(const std::string& filename);
  void readData(const std::string& filename);
  int get_n_nodes() const;
  int get_n_grids() const;
  const std::valarray<Point<double,2>>& get_points() const;
  const Point<double,2>& get_point(int _i) const;
  const std::valarray<Vector<int,3>>& get_grids() const;
  const Vector<int,3>& get_grid(int _i) const;
};


EasyMesh::EasyMesh(){};

EasyMesh::EasyMesh(const std::string& filename){
  readData(filename);
}

int EasyMesh::get_n_nodes() const{
  return nodes.size();
}

int EasyMesh::get_n_grids() const{
  return grids.size();
}

const std::valarray<Point<double,2>>& EasyMesh::get_points() const{
  return nodes;
}

const Point<double,2>& EasyMesh::get_point(int _i) const{
  return nodes[_i];
}

const std::valarray<Vector<int,3>>& EasyMesh::get_grids() const{
  return grids;
}

const Vector<int,3>& EasyMesh::get_grid(int _i) const{
  return grids[_i];
}

void EasyMesh::readData(const std::string& filename){
  std::ifstream is((filename + ".n").c_str());
  int n_node, n_side, n_element;
  char garbage[64];
  is >> n_node >> n_element >> n_side;
  is.getline(garbage, 64);
  nodes.resize(n_node);
  for (int i = 0; i < n_node; i++){
    int p_index,p_boundary;
    double x,y;
    is >> p_index >> x >> y >> p_boundary;
    nodes[i].set_index(p_index);
    nodes[i].set_coord({x,y});
    nodes[i].set_boundary_mark(p_boundary);
  }
  is.close();
  is.open((filename + ".e").c_str());
  int n_ele;
  is >> n_ele;
  if (n_ele != n_element){
    std::cerr << "in element file: element number error." << std::endl;
    exit(-1);
  }
  int n_n;
  is >> n_n;
  if (n_n != n_node){
    std::cerr << "in element file: node number error." << std::endl;
    exit(-1);
  }
  int n_s;
  is >> n_s;
  if (n_s != n_side){
    std::cerr << "in element file: side number error." << std::endl;
    exit(-1);
  }
  is.getline(garbage, 64);
  grids.resize(n_element);
  for (size_t i = 0; i < n_element; i++){
    int e_index, v0, v1, v2;
    int b0, b1, b2,n0, n1, n2;
    is >> e_index
       >> v0 >> v1 >> v2
       >> n0 >> n1 >> n2
       >> b0 >> b1 >> b2;
    grids[i](0) = v0;
    grids[i](1) = v1;
    grids[i](2) = v2;
    const Point<double,2>& p0 = nodes[v0];
    const Point<double,2>& p1 = nodes[v1];
    const Point<double,2>& p2 = nodes[v2];
    if ((p1.get_coord(0) - p0.get_coord(0)) * (p2.get_coord(1) - p0.get_coord(1)) - (p1.get_coord(1) - p0.get_coord(1)) * (p2.get_coord(0) - p0.get_coord(0)) < 0){
      std::cerr << "vertices of element " << e_index 
	        << " is not correctly ordered." << std::endl;
    }
    
  }
  is.close();
}













#else
// DO NOTHING.
#endif
